package com.hejia.bulbul.controller;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hejia.alauda.entity.Channel;
import com.hejia.alauda.service.PopularizeService;
import com.hejia.alauda.utils.DateTimeUtil;
import com.hejia.alauda.utils.HttpResponse;
import com.hejia.alauda.utils.Pager;
import com.hejia.alauda.utils.PagerHelper;
import com.hejia.bulbul.entity.ChannelAnalyse;
import com.hejia.bulbul.entity.ChannelDayStatistic;
import com.hejia.bulbul.service.ChannelStatisticService;

/**
 * 渠道控制器
 * 
 * @author hyr
 *
 */
@Controller
@RequestMapping("channels")
public class ChannelController {

	private static final Log Logger = LogFactory
			.getLog(ChannelController.class);

	@Resource
	private PopularizeService channelService;

	@Resource
	private ChannelStatisticService channelStatisticService;

	@RequestMapping
	public String list(String keyword, Pager<Channel> pager, ModelMap model) {

		pager = this.channelService.findChannelsByKeyword(keyword, pager);

		PagerHelper<Channel> helper = new PagerHelper<>();
		helper.setPager(pager);
		Map<String, String> map = new HashMap<>();
		if (keyword != null) {
			map.put("keyword", keyword);
		}
		helper.setParams(map);
		helper.setBaseUrl("/channels");

		model.put("pagerHelper", helper);
		model.put("keyword", keyword);
		model.put("channels", pager);

		return "channel/list";
	}

	@RequestMapping(method = RequestMethod.POST)
	@ResponseBody
	public HttpResponse add(Channel channel) {

		HttpResponse response = new HttpResponse();

		try {
			if (channelService.isExistChannel(channel)) {
				response.setCode(HttpResponse.CODE_INTERNAL_SERVER_ERROR);
				response.setStatus(HttpResponse.STATUS_FAIL);
				response.setMessage("渠道名称或渠道号已存在");
				response.setData(channel);
			} else {
				channel = channelService.addChannel(channel);
				response.setCode(HttpResponse.CODE_OK);
				response.setStatus(HttpResponse.STATUS_SUCCESS);
				response.setMessage("添加渠道成功");
				response.setData(channel);
			}
		} catch (Exception e) {
			Logger.error("添加渠道失败", e);
			response.setCode(HttpResponse.CODE_INTERNAL_SERVER_ERROR);
			response.setStatus(HttpResponse.STATUS_FAIL);
			response.setMessage("添加渠道失败 " + e.getMessage());
			response.setData(channel);
		}

		return response;
	}

	@RequestMapping(value = "{id}/edit")
	public String edit(@PathVariable Long id, ModelMap model) {

		Channel channel = this.channelService.findChannelById(id);
		model.put("channel", channel);

		return "channel/edit";
	}

	@RequestMapping(value = "{id}", method = RequestMethod.PUT)
	@ResponseBody
	public HttpResponse update(Channel channel) {

		HttpResponse response = new HttpResponse();

		try {
			if (channelService.isExistChannel(channel)) {
				response.setCode(HttpResponse.CODE_INTERNAL_SERVER_ERROR);
				response.setStatus(HttpResponse.STATUS_FAIL);
				response.setMessage("渠道名称或渠道号已存在");
				response.setData(channel);
			} else {
				channelService.updateChannel(channel);
				response.setCode(HttpResponse.CODE_OK);
				response.setStatus(HttpResponse.STATUS_SUCCESS);
				response.setMessage("更新渠道成功");
				response.setData(channel);
			}

		} catch (Exception e) {
			Logger.error("更新渠道失败", e);
			response.setCode(HttpResponse.CODE_INTERNAL_SERVER_ERROR);
			response.setStatus(HttpResponse.STATUS_FAIL);
			response.setMessage("更新渠道失败 " + e.getMessage());
		}

		return response;
	}

	@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
	@ResponseBody
	public HttpResponse delete(@PathVariable Long id) {

		HttpResponse response = new HttpResponse();

		try {
			channelService.deleteChannel(id);
			response.setCode(HttpResponse.CODE_OK);
			response.setStatus(HttpResponse.STATUS_SUCCESS);
			response.setMessage("删除渠道成功");

		} catch (Exception e) {
			Logger.error("删除渠道失败", e);
			response.setCode(HttpResponse.CODE_INTERNAL_SERVER_ERROR);
			response.setStatus(HttpResponse.STATUS_FAIL);
			response.setMessage("删除渠道失败 " + e.getMessage());
		}

		return response;
	}

	@RequestMapping(value = "analyse")
	public String analyse(
			Long biggerCategoryId, 
			Long categoryId, 
			Long popularizeId, 
			String number,
			Date startDate,
			Date endDate, ModelMap model) {

		Date now = new Date();
		if (startDate == null) {
			startDate = DateTimeUtil.getDateDay(new Date());
		} else {
			startDate = DateTimeUtil.getDateDay(startDate);
		}
		if (endDate == null) {
			endDate = DateTimeUtil.getDateAndMaxTime(new Date());
		} else {
			endDate = DateTimeUtil.getDateAndMaxTime(endDate);
		}

		ChannelAnalyse channelAnalyse = this.channelStatisticService
				.analyseChannel(biggerCategoryId, categoryId, popularizeId, number, startDate, endDate);

		model.put("now", now);
		model.put("biggerCategoryId", biggerCategoryId);
		model.put("categoryId", categoryId);
		model.put("popularizeId", popularizeId);
		model.put("number", number);
		model.put("startDate", startDate);
		model.put("endDate", endDate);
		model.put("channelAnalyse", channelAnalyse);

		return "channel/analyse";
	}

	@RequestMapping(value = "analyse.xlsx")
	public void exportAnalyse(
			HttpServletRequest request,
			HttpServletResponse response,
			Long biggerCategoryId,
			Long categoryId,
			Long popularizeId,
			String number,
			Date startDate,
			Date endDate) {

		if (startDate == null) {
			startDate = DateTimeUtil.getDateDay(new Date());
		} else {
			startDate = DateTimeUtil.getDateDay(startDate);
		}
		if (endDate == null) {
			endDate = DateTimeUtil.getDateAndMaxTime(new Date());
		} else {
			endDate = DateTimeUtil.getDateAndMaxTime(endDate);
		}

		ChannelAnalyse channelAnalyse = this.channelStatisticService
				.analyseChannel(biggerCategoryId, categoryId, popularizeId, number, startDate, endDate);

		String analyseExcelFile = request.getSession().getServletContext()
				.getRealPath("/WEB-INF/ftl/channel/analyse.xlsx");
		InputStream inputStream = null;
		try {

			inputStream = new FileInputStream(analyseExcelFile);
			Workbook workbook = WorkbookFactory.create(inputStream);
			Sheet sheet = workbook.getSheetAt(0);
			Row row = sheet.getRow(2);

			row.getCell(0).setCellValue(
					String.format("%s[%s]", channelAnalyse.getName(),
							channelAnalyse.getChannelNumber()));
			row.getCell(1).setCellValue(channelAnalyse.getRegisterCount());
			row.getCell(2).setCellValue(channelAnalyse.getRegisterTradeUserCount());
			row.getCell(3).setCellValue(channelAnalyse.getRegisterPaidUserCount());
			row.getCell(4).setCellValue(channelAnalyse.getRealNameCount());
			row.getCell(5).setCellValue(channelAnalyse.getPaidUserCount());
			row.getCell(6).setCellValue(channelAnalyse.getNewTradeUserCount());
			row.getCell(7).setCellValue(channelAnalyse.getRepeatOrderUserCount());
			row.getCell(8).setCellValue(channelAnalyse.getRegisterUserOrderCount());
			row.getCell(9).setCellValue(channelAnalyse.getRegisterUserPaidOrderCount());
			row.getCell(10).setCellValue(channelAnalyse.getOrderCount());
			row.getCell(11).setCellValue(channelAnalyse.getPaidOrderCount());
			row.getCell(12).setCellValue(channelAnalyse.getRepeatOrderCount());
			row.getCell(13).setCellValue(channelAnalyse.getRegisterUserPaymentAmount().doubleValue());
			row.getCell(14).setCellValue(channelAnalyse.getPaymentAmount().doubleValue());
			row.getCell(15).setCellValue(channelAnalyse.getNewTradeOrderAmount().doubleValue());
			row.getCell(16).setCellValue(channelAnalyse.getRepeatOrderAmount().doubleValue());

			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			response.setContentType("application/vnd.ms-excel");
			response.addHeader("Content-Disposition", String.format(
					"attachment; filename=\"%s_%s_%s%s.xlsx\"", 
					new String(channelAnalyse.getName().getBytes("gbk"),"iso-8859-1"), 
					format.format(startDate),
					format.format(endDate), 
					new String("渠道统计".getBytes("gbk"), "iso-8859-1")));

			response.setDateHeader("Expires", 0);
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Pragma", "no-cache");

			OutputStream outputStream = response.getOutputStream();
			workbook.write(outputStream);

			outputStream.close();
			response.flushBuffer();

		} catch (Exception e) {
			Logger.error("导出渠道分析Excel失败", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					Logger.error("关闭输入流失败", e);
				}
			}
		}
	}
	
	/**
	 * 导出渠道日明细数据
	 * @param request
	 * @param response
	 * @param biggerCategoryId
	 * @param categoryId
	 * @param popularizeId
	 * @param number
	 * @param startDate
	 * @param endDate
	 */
	@RequestMapping(value = "dailyanalyse.xlsx")
	public void exportDailyAnalyse(
			HttpServletRequest request,
			HttpServletResponse response,
			Long biggerCategoryId,
			Long categoryId,
			Long popularizeId,
			String number,
			Date startDate,
			Date endDate) {

		if (startDate == null) {
			startDate = DateTimeUtil.getDateDay(new Date());
		} else {
			startDate = DateTimeUtil.getDateDay(startDate);
		}
		if (endDate == null) {
			endDate = DateTimeUtil.getDateAndMaxTime(new Date());
		} else {
			endDate = DateTimeUtil.getDateAndMaxTime(endDate);
		}

		String name = this.channelStatisticService.findChannelName(biggerCategoryId, categoryId, popularizeId, number);
		List<ChannelDayStatistic> channelDayStatistics = this.channelStatisticService
				.countChannelDailyData(biggerCategoryId, categoryId, popularizeId, number, startDate, endDate);

		String analyseExcelFile = request.getSession().getServletContext()
				.getRealPath("/WEB-INF/ftl/channel/dailyanalyse.xlsx");
		InputStream inputStream = null;
		
		try {

			inputStream = new FileInputStream(analyseExcelFile);
			Workbook workbook = WorkbookFactory.create(inputStream);
			Sheet sheet = workbook.getSheetAt(0);
			for(int i = 0; i < channelDayStatistics.size(); i++){
				ChannelDayStatistic statistic = channelDayStatistics.get(i);
				int rowIndex = i + 2;
				Row row = sheet.getRow(rowIndex);
				if(row == null){
					row = createRow(sheet, rowIndex);
				}
				
				NumberFormat percentFormat = NumberFormat.getPercentInstance();
				percentFormat.setMaximumFractionDigits(0);
				DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
				DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
				
				row.getCell(0).setCellValue(format.format(statistic.getDate()));
				row.getCell(1).setCellValue(statistic.getRegisterCount());
				row.getCell(2).setCellValue(percentFormat.format(statistic.getRegisterRatio()));
				row.getCell(3).setCellValue(statistic.getNewTradeUserCount());
				row.getCell(4).setCellValue(percentFormat.format(statistic.getNewTradeUserRatio()));
				row.getCell(5).setCellValue(statistic.getAccumulativeRegisterCount());
				row.getCell(6).setCellValue(statistic.getAccumulativeTradeUserCount());
				row.getCell(7).setCellValue(percentFormat.format(statistic.getAccumulativeTradeUserRatio()));
				row.getCell(8).setCellValue(decimalFormat.format(statistic.getTradeAmount()));
				row.getCell(9).setCellValue(percentFormat.format(statistic.getTradeAmountRatio()));
				row.getCell(10).setCellValue(decimalFormat.format(statistic.getAccumulativeTradeAmount()));
				row.getCell(11).setCellValue(statistic.getNewAppTradeUserCount());
				row.getCell(12).setCellValue(statistic.getAllNewAppTradeUserCount());
				row.getCell(13).setCellValue(statistic.getAccumulativeAppTradeUserCount());
			}
			
			DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			response.setContentType("application/vnd.ms-excel");
			response.addHeader("Content-Disposition", String.format(
					"attachment; filename=\"%s_%s_%s%s.xlsx\"", 
					new String(name.getBytes("gbk"), "iso-8859-1"), 
					format.format(startDate), format.format(endDate), 
					new String("渠道统计".getBytes("gbk"), "iso-8859-1")));

			response.setDateHeader("Expires", 0);
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Pragma", "no-cache");

			OutputStream outputStream = response.getOutputStream();
			workbook.write(outputStream);

			outputStream.close();
			response.flushBuffer();

		} catch (Exception e) {
			Logger.error("导出渠道日明细数据失败", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					Logger.error("关闭输入流失败", e);
				}
			}
		}
	}
	
	/**
	 * 创建行
	 * @param sheet
	 * @param rowIndex
	 * @return
	 */
	private Row createRow(Sheet sheet, int rowIndex) {
		Row row = sheet.createRow(rowIndex);
		for(int i = 0; i < 14; i++){
			Cell cell = row.createCell(i);
			cell.setCellStyle(sheet.getRow(rowIndex - 1).getCell(i).getCellStyle());
		}
		return row;
	}

	@InitBinder
	// 此处的参数也可以是ServletRequestDataBinder类型
	public void initBinder(WebDataBinder binder) throws Exception {
		// 注册自定义的属性编辑器
		// 1、日期
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		CustomDateEditor dateEditor = new CustomDateEditor(df, true);
		// 表示如果命令对象有Date类型的属性，将使用该属性编辑器进行类型转换
		binder.registerCustomEditor(Date.class, dateEditor);

	}
}
